using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;

namespace ad {
	public class IniFiler {
		private String _ini_file_name = null;
		private Dictionary<Int32, string> _ini_file_lines = null;
		private Exception _last_exception = null;
		private IniData _ini_data = null;
		private Boolean _is_loaded = false;
		public IniFiler() {
		}
		public IniFiler(String IniFileName) {
			_ini_file_name = IniFileName;
			_is_loaded = false;
			GetData();
		}
		public String IniFileName {
			get { return _ini_file_name; }
			set {
				_ini_file_name = value;
				_is_loaded = false;
				GetData();
			}
		}

		public IniData GetData(String IniFileName) {
			_ini_file_name = IniFileName;
			return GetData(_ini_file_name, false);
		}
		public IniData GetData() {
			return GetData(_ini_file_name, false);
		}
		public IniData GetData(String IniFileName, Boolean Reload) {
			if (_is_loaded && _ini_data != null && Reload != true)
				return _ini_data;
			_ini_file_lines = new Dictionary<int,string>();
			try {
				using (StreamReader _sr = new StreamReader(_ini_file_name)) {
					String _line; Int32 i = 0;
					while ((_line = _sr.ReadLine()) != null) {
						_ini_file_lines.Add(i, _line); i++;
					}
				}
				_ini_data = new IniData(_ini_file_lines);
			}
			catch (Exception e) {
				_last_exception = e;
			}
			_is_loaded = true;
			return _ini_data;
		}
		
		public String GetKey(String SectionName, String KeyName) {
			return GetKey(SectionName, KeyName, "");
		}
		
		public String GetKey(String SectionName, String KeyName, String DefaultValue) {
			Dictionary<string, string> _section_keys;
			Boolean _section_exist = _ini_data.TryGetValue(SectionName, out _section_keys);
			if (_section_exist) {
				String _key_value;
				Boolean _key_exist = _ini_data[SectionName].TryGetValue(KeyName, out _key_value);
				if (_key_exist)
					return _key_value;
			}
			return DefaultValue;
		}

		public void SetKey(String SectionName, String KeyName, String KeyValue) {
			if (!_ini_data.ContainsKey(SectionName))
				_ini_data.Add(SectionName, new Dictionary<string, string>());
			if (!_ini_data[SectionName].ContainsKey(KeyName)) {
				_ini_data[SectionName].Add(KeyName, KeyValue);
			}
			else {
				_ini_data[SectionName][KeyName] = KeyValue;
			}
		}
	}

	public class IniData: Dictionary<string, Dictionary<string, string>> { //[String Section][String Key, String Value]
        private Regex rx =
            new Regex(@"^\s*(?<comment>(\'|\#|\;)*)\s*((\[\s*(?<section>\w+)\s*\]){1}|((?<key>(\S)+)\s*\=\s*(?<val>(\w|:|\\)+)){1}).*$",
            RegexOptions.Compiled | RegexOptions.IgnoreCase);
        private MatchCollection matches = null;
		private String _comment = "";
		private String _section = "";
		private String _key = "";
		private String _value = "";

		//private _lines;

		public IniData() {
		}
		
		internal IniData(Dictionary<Int32, string> _ini_file_lines) {
			foreach (KeyValuePair<Int32, string> _line in _ini_file_lines) {
				matches = rx.Matches(_line.Value);
				if (matches.Count > 0) {
					_comment = matches[0].Groups["comment"].Value;
					if (_comment == "") {
						if (matches[0].Groups["section"].Value != "") {
							_section = matches[0].Groups["section"].Value;
							this.Add(_section, new Dictionary<string, string>());
						}
						_key = matches[0].Groups["key"].Value;
						_value = matches[0].Groups["val"].Value;
						if (_key != "" && _value != "" && _section != "") {
							this[_section].Add(_key, _value);
						}
					}
				}
			}
		}
	}
}
